home *** CD-ROM | disk | FTP | other *** search
Lisp/Scheme | 1994-05-28 | 17.7 KB | 603 lines | [TEXT/xlsp] |
- ;; functions missing that are part of common lisp, and commonly used
-
- ;; It is assumed you are using XLISP 2.1g with all Common Lisp related options
- ;; turned on before you load this file.
-
- ;; Author either unknown or Tom Almy unless indicated.
-
- (in-package "XLISP")
-
- ; (unintern sym) - remove a symbol from the oblist
- #-:packages
- (defun unintern (symbol)
- (let ((subhash (hash symbol (length *obarray*))))
- (cond ((member symbol (aref *obarray* subhash))
- (setf (aref *obarray* subhash)
- (delete symbol (aref *obarray* subhash)))
- t)
- (t nil))))
-
- (export '(pairlis copy-list copy-alist copy-tree signum))
-
- ;; pairlis does not check for lengths of keys and values being unequal
-
- (defun pairlis (keys values &optional list)
- (nconc (mapcar #'cons keys values) list))
-
- (defun copy-list (list) (append list 'nil))
-
- (defun copy-alist (list)
- (if (null list)
- 'nil
- (cons (if (consp (car list))
- (cons (caar list) (cdar list))
- (car list))
- (copy-alist (cdr list)))))
-
- (defun copy-tree (list)
- (if (consp list)
- (cons (copy-tree (car list)) (copy-tree (cdr list)))
- list))
-
- (defun signum (x)
- (cond ((not (numberp x)) (error "~s is not a number" x))
- ((zerop x) x)
- (T (/ x (abs x)))))
-
- (export '(remf incf decf push pushnew pop))
-
- ; Cruddy but simple versions of these functions.
- ; Commented out since XLISP will now expand macros once, making
- ; good version much preferred.
-
- ;(defmacro incf (var &optional (delta 1))
- ; `(setf ,var (+ ,var ,delta)))
-
- ;(defmacro decf (var &optional (delta 1))
- ; `(setf ,var (- ,var ,delta)))
-
- ;(defmacro push (v l)
- ; `(setf ,l (cons ,v ,l))))
-
- ;(defmacro pushnew (a l &rest args)
- ; `(unless (member ,a ,l ,@args) (push ,a ,l) nil))
-
- ;(defmacro pop (l)
- ; `(prog1 (first ,l) (setf ,l (rest ,l)))))
-
-
- ; This is what one really needs to do for incf decf and
- ; (in common.lsp) push and pop. The setf form must only be evaluated once.
- ; But is it worth all this overhead for correctness?
- ; (By Tom Almy)
-
- (defun |DoForm| (form) ; returns (cons |list for let| |new form|)
- (let* ((args (rest form)) ; raw form arguments
- (letlist (mapcan #'(lambda (x) (when (consp x)
- (list (list (gensym) x))))
- form))
- (revlist (mapcar #'(lambda (x) (cons (second x) (first x)))
- letlist))
- (newform (cons (first form) (sublis revlist args))))
- (cons letlist newform)))
-
- (defun |RemProp| (l prop)
- (do ((cl l (cddr cl))
- (flg nil cl))
- ((atom cl) nil) ; none found
- (cond ((atom (cdr l))
- (error "odd length property list"))
- ((eq (car cl) prop) ; a match!
- (if flg ; different if first in list from later
- (rplacd (cdr flg) (cddr cl))
- (setq l (cddr l)))
- (return (list l))))))
-
- (defmacro remf (form prop &aux (remres (gensym)))
- (if (and (consp form) (some #'consp form))
- (let ((retval (|DoForm| form)))
- `(let* ( ,@(car retval)
- (,remres (|RemProp| ,(cdr retval) ,prop)))
- (if ,remres
- (progn (setf ,(cdr retval) (car ,remres))
- t)
- nil)))
- `(let ((,remres (|RemProp| ,form ,prop)))
- (if ,remres (progn (setf ,form (car ,remres)) t)
- nil))))
-
- #-packages
- (unintern '|RemProp|)
-
- (defmacro incf (form &optional (delta 1))
- (if (and (consp form) (some #'consp form))
- (let ((retval (|DoForm| form)))
- `(let ,(car retval)
- (setf ,(cdr retval)
- (+ ,(cdr retval) ,delta))))
- `(setf ,form (+ ,form ,delta))))
-
- (defmacro decf (form &optional (delta 1))
- (if (and (consp form) (some #'consp form))
- (let ((retval (|DoForm| form)))
- `(let ,(car retval)
- (setf ,(cdr retval)
- (- ,(cdr retval) ,delta))))
- `(setf ,form (- ,form ,delta))))
-
- (defmacro push (val form)
- (if (and (consp form) (some #'consp form))
- (let ((retval (|DoForm| form)))
- `(let ,(car retval)
- (setf ,(cdr retval)
- (cons ,val ,(cdr retval)))))
- `(setf ,form (cons ,val ,form))))
-
- (defmacro pop (form)
- (if (and (consp form) (some #'consp form))
- (let ((retval (|DoForm| form)))
- `(let ,(car retval)
- (prog1 (first ,(cdr retval))
- (setf ,(cdr retval)
- (rest ,(cdr retval))))))
- `(prog1 (first ,form)
- (setf ,form (rest ,form)))))
-
-
- (defmacro pushnew (val form &rest rest)
- (if (and (consp form) (some #'consp form))
- (let ((retval (|DoForm| form)))
- `(let ,(car retval)
- (setf ,(cdr retval)
- (adjoin ,val ,(cdr retval) ,@rest))))
- `(setf ,form (adjoin ,val ,form ,@rest))))
-
- #-packages
- (unintern '|DoForm|)
-
- ;; Hyperbolic functions Ken Whedbee from CLtL
-
- (export '(logtest cis sinh cosh tanh asinh acosh atanh))
-
- (defun logtest (x y) (not (zerop (logand x y))))
-
- (defconstant imag-one #C(0.0 1.0))
-
- (defun cis (x) (exp (* imag-one x)))
-
-
- (defun sinh (x) (/ (- (exp x) (exp (- x))) 2.0))
- (defun cosh (x) (/ (+ (exp x) (exp (- x))) 2.0))
- (defun tanh (x) (/ (sinh x) (cosh x)))
-
- (defun asinh (x) (log (+ x (sqrt (+ 1.0 (* x x))))))
- (defun acosh (x)
- (log (+ x
- (* (1+ x)
- (sqrt (/ (1- x) (1+ x)))))))
- (defun atanh (x)
- (when (or (= x 1.0) (= x -1.0))
- (error "~s is a logarithmic singularity" x))
- (log (/ (1+ x) (sqrt (- 1.0 (* x x))))))
-
-
-
- ;; Additional Common Lisp Functions by Luke Tierney
- ;; from xlisp-stat
-
- ;;
- ;; Defsetf and documentation functions
- ;; Corrected for Common Lisp compatibility (requires XLISP-PLUS 2.1e)
- ;; Modified by Tom Almy, 7/92
- ;; Corrected again in 6/93
- ;; and again (Luke Tierney) 11/93
- ;;
-
- (export '(defsetf))
-
- (defun apply-arg-rotate (f args)
- (apply f (list 'quote (car (last args))) (butlast args)))
-
- ; (defsetf) - define setf method
- (defmacro defsetf (sym first &rest rest)
- (if (symbolp first)
- `(progn (setf (get ',sym '*setf*) #',first)
- (remprop ',sym '*setf-lambda*)
- ',sym)
- (let ((f `#'(lambda ,(append (car rest) first) ,@(cdr rest)))
- (args (gensym)))
- `(progn
- (setf (get ',sym '*setf-lambda*) ; changed *setf* to *setf-lambda*
- #'(lambda (&rest ,args) (apply-arg-rotate ,f ,args)))
- (remprop ',sym '*setf*)
- ',sym))))
-
-
- ;;;;
- ;;;;
- ;;;; Modules, provide and require: Luke Tierney, from xlisp-stat
- ;;;;
- ;;;;
-
- ; Uncomment these if you want them. It's non-standard, and nothing else
- ; in this distribution uses them, so I'm commenting them out. Tom Almy
-
- #|
- (defvar *modules*)
-
- (defun provide (name)
- (pushnew name *modules* :test #'equal))
-
- (defun require (name &optional (path name))
- (let ((name (string name))
- (path (string path)))
- (unless (member name *modules* :test #'equal)
- (if (load path)
- t
- (load (strcat *default-path* path))))))
- |#
- ;;;;
- ;;;;
- ;;;; Miscellaneous Functions: Luke Tierney
- ;;;; from xlisp-stat
- ;;;;
-
- (export '(equalp y-or-n-p yes-or-no-p functionp with-input-from-string
- with-output-to-string with-open-file))
-
- ; equalp rewritten by Tom Almy to better match Common Lisp
- (defun equalp (x y)
- (cond ((equal x y) t)
- ((numberp x) (if (numberp y) (= x y) nil))
- ((characterp x) (if (characterp y) (char-equal x y) nil))
- ((and (or (arrayp x) (stringp x))
- (or (arrayp y) (stringp y))
- (eql (length x) (length y)))
- (every #'equalp x y))))
-
- ; Modified by TAA
- #-:getkey
- (defun y-or-n-p (&rest args)
- (reset-system)
- (when args (fresh-line) (apply #'format *terminal-io* args))
- (do ((answer (string-trim " " (read-line))
- (string-trim " " (read-line))))
- ((or (string-equal answer "Y")
- (string-equal answer "N"))
- (string-equal answer "Y"))
- (princ " Answer \"y\" or \"n\": " *terminal-io*)))
-
- #+:getkey
- (defun y-or-n-p (&rest args)
- (when args (fresh-line) (apply #'format *terminal-io* args))
- (do ((answer (princ (int-char (get-key)))
- (princ (int-char (get-key)))))
- ((or (char-equal answer #\Y)
- (char-equal answer #\N))
- (char-equal answer #\Y))
- (princ "\nAnswer \"y\" or \"n\": " *terminal-io*)))
-
-
- ; Based on y-or-n-p
- (defun yes-or-no-p (&rest args)
- (reset-system)
- (when args (fresh-line) (apply #'format *terminal-io* args))
- (do ((answer (string-trim " " (read-line))
- (string-trim " " (read-line))))
- ((or (string-equal answer "YES")
- (string-equal answer "NO"))
- (string-equal answer "YES"))
- (princ " Answer \"yes\" or \"no\": " *terminal-io*)))
-
- ; Improved by TAA to match common lisp definition
- (defun functionp (x)
- (if (typep x '(or closure subr symbol))
- t
- (and (consp x) (eq (car x) 'lambda))))
-
- ;(defmacro with-input-from-string (stream-string &rest body)
- ; (let ((stream (first stream-string))
- ; (string (second stream-string)))
- ; `(let ((,stream (make-string-input-stream ,string)))
- ; (progn ,@body))))
-
-
- (defmacro with-input-from-string
- (stream-string &rest body)
- (let ((stream (first stream-string))
- (string (second stream-string))
- (start (second (member :start (cddr stream-string))))
- (end (second (member :end (cddr stream-string))))
- (index (second (member :index (cddr stream-string)))))
- (when (null start) (setf start 0))
- (if index
- (let ((str (gensym)))
- `(let* ((,str ,string)
- (,stream (make-string-input-stream ,str
- ,start
- ,end)))
- (prog1 (progn ,@body)
- (setf ,index
- (- (length ,str)
- (length (get-output-stream-list
- ,stream)))))))
- `(let ((,stream (make-string-input-stream ,string ,start ,end)))
- (progn ,@body)))))
-
-
- (defmacro with-output-to-string (str-list &rest body)
- (let ((stream (first str-list)))
- `(let ((,stream (make-string-output-stream)))
- (progn ,@body)
- (get-output-stream-string ,stream))))
-
- (defmacro with-open-file (stream-file-args &rest body)
- (let ((stream (first stream-file-args))
- (file-args (rest stream-file-args)))
- `(let ((,stream (open ,@file-args)))
- (unwind-protect
- (progn ,@body)
- (when ,stream (close ,stream))))))
-
- (export '(eval-when declare proclaim special))
- ;; Dummy function to allow importing CL code
- (defmacro eval-when (when &rest body)
- (if (or (member 'eval when) (member 'execute when))
- `(progn ,@body)))
- (defmacro declare (&rest args)
- (if *displace-macros*
- (dolist (a args)
- (if (eq (first a) 'special)
- (return (cerror "special ignored"
- "special declarations are not supported"))))))
- (defun proclaim (decl)
- (if (eq (first decl) 'special)
- (dolist (s (rest decl))
- (mark-as-special s))))
-
-
- ;; array functions. KCW from Kyoto Common Lisp
-
- (export '(fill replace acons))
-
- (defun fill (sequence item
- &key (start 0) end)
- (when (null end) (setf end (length sequence)))
- (do ((i start (1+ i)))
- ((>= i end) sequence)
- (setf (elt sequence i) item)))
-
-
- (defun replace (sequence1 sequence2
- &key (start1 0) end1
- (start2 0) end2)
- (when (null end1) (setf end1 (length sequence1)))
- (when (null end2) (setf end2 (length sequence2)))
- (if (and (eq sequence1 sequence2)
- (> start1 start2))
- (do* ((i 0 (1+ i))
- (l (if (< (- end1 start1) (- end2 start2))
- (- end1 start1)
- (- end2 start2)))
- (s1 (+ start1 (1- l)) (1- s1))
- (s2 (+ start2 (1- l)) (1- s2)))
- ((>= i l) sequence1)
- (setf (elt sequence1 s1) (elt sequence2 s2)))
- (do ((i 0 (1+ i))
- (l (if (< (- end1 start1)(- end2 start2))
- (- end1 start1)
- (- end2 start2)))
- (s1 start1 (1+ s1))
- (s2 start2 (1+ s2)))
- ((>= i l) sequence1)
- (setf (elt sequence1 s1) (elt sequence2 s2)))))
-
-
- (defun acons (x y a) ; from CLtL
- (cons (cons x y) a))
-
-
- ;; more set functions. KCW from Kyoto Common Lisp
-
- ;; Modified to pass keys to subfunctions without checking here
- ;; (more efficient)
-
- ;; (Tom Almy states:) we can't get the destructive versions of union
- ;; intersection, and set-difference to run faster than the non-destructive
- ;; subrs. Therefore we will just have the destructive versions do their
- ;; non-destructive counterparts
-
- (export '(nunion nintersection nset-difference
- set-exclusive-or nset-exclusive-or))
-
- (setf (symbol-function 'nunion)
- (symbol-function 'union)
- (symbol-function 'nintersection)
- (symbol-function 'intersection)
- (symbol-function 'nset-difference)
- (symbol-function 'set-difference))
-
- (defun set-exclusive-or (list1 list2 &rest rest)
- (append (apply #'set-difference list1 list2 rest)
- (apply #'set-difference list2 list1 rest)))
-
- (defun nset-exclusive-or (list1 list2 &rest rest)
- (nconc (apply #'set-difference list1 list2 rest)
- (apply #'set-difference list2 list1 rest)))
-
-
-
- ;;;;;
- ;;;;; Symbol and Package Functions
- ;;;;;
- #+:packages
- (export '(defpackage do-symbols do-external-symbols do-all-symbols
- apropos apropos-list))
-
- #+:packages
- (defmacro do-symbol-arrays (s res a body)
- (let ((arraysym (gensym))
- (isym (gensym))
- (asym (gensym))
- (listsym (gensym)))
- `(let ((,arraysym ,a)
- (,isym 0)
- (,asym nil)
- (,listsym nil)
- (,s nil))
- (block nil
- (tagbody
- new-array
- (when (null ,arraysym)
- (setf ,s nil)
- (return ,res))
- (setf ,asym (first ,arraysym) ,arraysym (rest ,arraysym) ,isym -1)
- new-list
- (setf ,isym (1+ ,isym))
- (if (<= 199 ,isym) (go new-array))
- (setf ,listsym (aref ,asym ,isym))
- new-item
- (if (null ,listsym) (go new-list))
- (setf ,s (first ,listsym) ,listsym (rest ,listsym))
- (tagbody ,@body)
- (go new-item))))))
-
- #+:packages
- (defmacro do-symbols (spr &rest body)
- (let ((packsym (gensym))
- (usessym (gensym))
- (arraysym (gensym)))
- `(let* ((,packsym ,(if (second spr) (second spr) '*package*))
- (,usessym (package-use-list ,packsym))
- (,arraysym (cons (package-obarray ,packsym nil)
- (mapcar #'package-obarray
- (cons ,packsym ,usessym)))))
- (do-symbol-arrays ,(first spr) ,(third spr) ,arraysym ,body))))
-
- #+:packages
- (defmacro do-external-symbols (spr &rest body)
- (let ((packsym (gensym))
- (arraysym (gensym)))
- `(let* ((,packsym ,(if (second spr) (second spr) '*package*))
- (,arraysym (list (package-obarray ,packsym))))
- (do-symbol-arrays ,(first spr) ,(third spr) ,arraysym ,body))))
-
- #+:packages
- (defmacro do-all-symbols (sr &rest body)
- (let ((packsym (gensym))
- (arraysym (gensym)))
- `(let* ((,packsym (list-all-packages))
- (,arraysym nil))
- (dolist (p ,packsym)
- (push (package-obarray p) ,arraysym)
- (push (package-obarray p nil) ,arraysym))
- (do-symbol-arrays ,(first sr) ,(second sr) ,arraysym ,body))))
-
- #+:packages
- (defmacro defpackage (pname &rest options)
- `(let* ((pname ',pname)
- (options ',options)
- (pack (find-package ',pname))
- (nicknames nil))
- (dolist (opt options)
- (if (eq (first opt) :nicknames)
- (setf nicknames (append (rest opt) nicknames))))
- (if pack
- (rename-package pack
- pname
- (mapcar #'string
- (append nicknames (package-nicknames pack))))
- (setf pack (make-package pname :nicknames
- (mapcar #'string nicknames))))
- (dolist (opt options)
- (case (first opt)
- (:shadow (shadow (mapcar #'string (rest opt)) pack))
- (:shadowing-import-from
- (let ((from-pack (find-package (second opt))))
- (dolist (sname (rest (rest opt)))
- (multiple-value-bind (sym found)
- (find-symbol (string sname) from-pack)
- (if found
- (shadowing-import sym pack)
- (error "no symbol named ~s in package ~s"
- (string sname)
- from-pack))))))))
- (dolist (opt options)
- (if (eq (first opt) :use)
- (use-package (mapcar #'string (rest opt)) pack)))
- (dolist (opt options)
- (case (first opt)
- (:intern
- (dolist (sname (rest opt)) (intern (string sname) pack)))
- (:import-from
- (let ((from-pack (find-package (second opt))))
- (dolist (sname (rest (rest opt)))
- (multiple-value-bind (sym found)
- (find-symbol (string sname) from-pack)
- (if found
- (import sym pack)
- (error "no symbol named ~s in package ~s"
- (string sname)
- from-pack))))))))
- (dolist (opt options)
- (if (eq (first opt) :export)
- (dolist (sname (rest opt))
- (export (intern (string sname) pack) pack))))
- pack))
-
- #+:packages
- (defun apropos2 (s)
- (format t "~&~s" s)
- (when (fboundp s) (format t " Function"))
- (if (constantp s)
- (format t " Constant=~s" (symbol-value s))
- (when (boundp s) (format t " Value=~s" (symbol-value s)))))
-
- #+:packages
- (defun apropos (x &optional package)
- (if package
- (do-symbols (s package)
- (if (search x (string s) :test #'char-equal)
- (apropos2 s)))
- (do-all-symbols (s)
- (if (search x (string s) :test #'char-equal)
- (apropos2 s))))
- (values))
-
- #+:packages
- (defun apropos-list (x &optional package)
- (let ((res nil))
- (if package
- (do-symbols (s package res)
- (if (search x (string s) :test #'char-equal)
- (push s res)))
- (do-all-symbols (s res)
- (if (search x (string s) :test #'char-equal)
- (push s res))))))
-
-
- ;;;;;
- ;;;;; Additional Multipla Value Functions and Macros
- ;;;;;
-
- (export
- '(values-list multiple-value-list multiple-value-bind multiple-value-setq))
-
- (defun values-list (x) (apply #'values x))
-
- (defmacro multiple-value-list (form)
- `(multiple-value-call #'list ,form))
-
- (defmacro multiple-value-bind (vars form &rest body)
- `(multiple-value-call #'(lambda (&optional ,@vars &rest ,(gensym)) ,@body)
- ,form))
-
- (defmacro multiple-value-setq (variables form)
- (let* ((tvars (mapcar #'(lambda (x) (gensym "V")) variables))
- (pairs nil))
- (mapc #'(lambda (x y) (push y pairs) (push x pairs)) variables tvars)
- (if (null tvars) (push (gensym) tvars))
- `(multiple-value-bind ,tvars ,form (setq ,@pairs) ,(first tvars))))
-
- (push :common *features*)
-